package ntd.util.modular.other.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.tool.ToolSpring;
import ntd.util.frame.storage.bo.StorageInBO;
import ntd.util.frame.storage.bo.StorageOutBO;
import ntd.util.frame.storage.service.NtdStorageService;
import ntd.util.util.ToolPoi;
import ntd.util.util.ToolPoi2;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.MimetypesFileTypeMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/public/storage")
public class ControllerStorage {

    @Resource
    private NtdStorageService ntdStorageService;

    @GetMapping(value = "/transform")
    public void transform(String resource) throws IOException {
        byte[] bytes = ToolPoi.docToDocx(new ByteArrayInputStream(HttpUtil.downloadBytes(resource)));
        writeStream(RandomUtil.randomString(10) + ".docx", new ByteArrayInputStream(bytes));
    }

    @GetMapping(value = "/xls-to-xlsx")
    public void xlsToXlsx(String resource) {
        byte[] bytes = ToolPoi.xlsToXlsx(new ByteArrayInputStream(HttpUtil.downloadBytes(resource)));
        writeStream(RandomUtil.randomString(10) + ".xlsx", new ByteArrayInputStream(bytes));
    }

    @GetMapping(value = "/ppt-to-pdf")
    public void pptToPdf(String resource) {
        byte[] bytes = ToolPoi2.pptToPdf(new ByteArrayInputStream(HttpUtil.downloadBytes(resource)));
        writeStream(RandomUtil.randomString(10) + ".pdf", new ByteArrayInputStream(bytes));
    }

    @PostMapping("/stores")
    public List<StorageOutBO> stores(@RequestPart("files") MultipartFile[] files, @Valid StorageInBO storage) throws IOException {
        List<StorageOutBO> storageOutBOList = new ArrayList<>();
        for (MultipartFile file : files) {
            storage.setOriginName(file.getName());
            storage.setBytes(file.getBytes());
            storageOutBOList.add(ntdStorageService.store(storage));
        }
        return storageOutBOList;
    }

    @PostMapping("/store")
    public StorageOutBO store(@RequestPart MultipartFile file, @Valid StorageInBO storage) throws IOException {
        storage.setOriginName(file.getOriginalFilename());
        storage.setBytes(file.getBytes());
        return ntdStorageService.store(storage);
    }

    @GetMapping(value = "/get/{channelId}/{bucketName}/**")
    public void getUrlFile(@PathVariable("channelId") String channelId,
                           @PathVariable("bucketName") String bucketName) {
        String servletPath = ToolSpring.getRequest().getServletPath();

        StorageInBO storageInBO = new StorageInBO();
        storageInBO.setChannelBusinessId(channelId);
        storageInBO.setFileKey(StrUtil.subAfter(servletPath, StrUtil.format("/public/storage/get/{}/{}/", channelId, bucketName), false));
        storageInBO.setBucketName(bucketName);
        getFile(storageInBO);
    }

    @GetMapping(value = "/get-file")
    public void getFile(@Valid StorageInBO storage) {
        InputStream file = ntdStorageService.getFile(storage);
        writeStream(storage.getFileKey(), file);
    }

    private static void writeStream(String key, InputStream inputStream) {
        HttpServletResponse response = ToolSpring.getResponse();
        OutputStream outputStream = null;
        try {
            String contentType = new MimetypesFileTypeMap().getContentType(key);
            response.setContentType(contentType);
            response.setHeader("Content-Disposition", "inline;filename=" + FileUtil.getName(key));
            outputStream = response.getOutputStream();
            byte[] buff = new byte[2048];
            int length = 0;
            while ((length = inputStream.read(buff)) > 0) {
                outputStream.write(buff, 0, length);
                outputStream.flush();
            }
            response.setHeader("Cache-Control", "private");
            response.setDateHeader("Expires", 0);
        } catch (Exception e) {

        } finally {
            Opt.ofNullable(outputStream).ifPresent(IoUtil::close);
            Opt.ofNullable(inputStream).ifPresent(IoUtil::close);
        }
    }

    @GetMapping("/generate-url")
    public String generateUrl(@Valid StorageInBO storage) {
        return ntdStorageService.generateUrl(storage);
    }
}
